<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>百度热搜爬虫</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="/style.css">
  <link rel="shortcut icon" href="/favicon.ico">
  <style>
    body {
      padding-top: 2rem;
      padding-bottom: 2rem;
    }
    .hot-item {
      transition: all 0.3s;
      border-left: 3px solid transparent;
      padding-left: 10px;
    }
    .hot-item:hover {
      transform: translateX(5px);
      border-left-color: #0d6efd;
      background-color: rgba(13, 110, 253, 0.05);
    }
    .hot-item.is-hot {
      border-left-color: #dc3545;
    }
    .hot-item.is-new {
      border-left-color: #198754;
    }
    .hot-badge {
      display: inline-block;
      width: 22px;
      height: 22px;
      line-height: 22px;
      text-align: center;
      border-radius: 50%;
      font-size: 12px;
      margin-right: 8px;
    }
    .hot-index {
      margin-left: auto;
      color: #6c757d;
      font-size: 0.9rem;
    }
    .spinner-border {
      width: 1rem;
      height: 1rem;
      margin-right: 0.5rem;
    }
    .btn-crawl {
      min-width: 100px;
    }
    .rank-1, .rank-2, .rank-3 {
      font-weight: bold;
    }
    .rank-1 .hot-badge {
      background-color: #dc3545;
      color: white;
    }
    .rank-2 .hot-badge {
      background-color: #fd7e14;
      color: white;
    }
    .rank-3 .hot-badge {
      background-color: #ffc107;
      color: black;
    }
    .timestamp {
      color: #6c757d;
      font-size: 0.8rem;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1 class="text-center mb-4">百度热搜爬虫</h1>
    
    <div class="row">
      <!-- 左侧控制面板 -->
      <div class="col-md-4">
        <div class="card">
          <div class="card-header bg-primary text-white">
            <h5 class="card-title mb-0">控制面板</h5>
          </div>
          <div class="card-body">
            <!-- 手动爬取按钮 -->
            <button id="manualCrawl" class="btn btn-primary btn-lg w-100 mb-3">
              <i class="bi bi-arrow-repeat"></i> 立即爬取百度热搜
            </button>
            
            <!-- 定时任务控制 -->
            <div class="mb-3">
              <label for="cronExpression" class="form-label">定时爬取设置</label>
              <div class="input-group">
                <input type="text" id="cronExpression" class="form-control" placeholder="*/3 * * * *" value="*/3 * * * *">
                <button id="startSchedule" class="btn btn-success" <%= isScheduleRunning ? 'disabled' : '' %>>
                  启动
                </button>
                <button id="stopSchedule" class="btn btn-danger" <%= isScheduleRunning ? '' : 'disabled' %>>
                  停止
                </button>
              </div>
              <div class="form-text">当前：<%= isScheduleRunning ? '定时任务运行中' : '定时任务已停止' %></div>
            </div>
            
            <!-- 历史数据 -->
            <div class="mb-3">
              <label class="form-label">历史热搜数据</label>
              <div class="d-grid">
                <button id="viewHistory" class="btn btn-secondary">查看历史数据</button>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 配置设置 -->
        <div class="card mt-3">
          <div class="card-header bg-info text-white">
            <h5 class="card-title mb-0">配置设置</h5>
          </div>
          <div class="card-body">
            <div class="mb-3">
              <label for="saveHistoryDays" class="form-label">保留历史天数</label>
              <input type="number" class="form-control" id="saveHistoryDays" min="1" max="30" value="7">
            </div>
            <div class="form-check form-switch mb-3">
              <input class="form-check-input" type="checkbox" id="autoStartSchedule" checked>
              <label class="form-check-label" for="autoStartSchedule">启动时自动开始定时任务</label>
            </div>
            <div class="d-grid">
              <button id="saveConfig" class="btn btn-primary">保存配置</button>
            </div>
          </div>
        </div>
      </div>
      
      <!-- 右侧热搜列表 -->
      <div class="col-md-8">
        <div class="card">
          <div class="card-header bg-danger text-white d-flex justify-content-between align-items-center">
            <h5 class="card-title mb-0">百度热搜榜</h5>
            <div class="timestamp">更新时间：<span id="updateTime"><%= timestamp %></span></div>
          </div>
          <div class="card-body p-0">
            <div class="list-group list-group-flush" id="hotList">
              <% if (hotSearchData && hotSearchData.length > 0) { %>
                <% hotSearchData.forEach(function(item, index) { %>
                  <div class="list-group-item d-flex align-items-center hot-item <%= item.isHot ? 'is-hot' : '' %> <%= item.isNew ? 'is-new' : '' %> rank-<%= index + 1 %>">
                    <span class="hot-badge"><%= item.rank || (index + 1) %></span>
                    <span class="hot-title"><%= item.title %></span>
                    
                    <span class="hot-index">
                      <% if (item.isHot) { %>
                        <span class="badge bg-danger">热</span>
                      <% } %>
                      <% if (item.isNew) { %>
                        <span class="badge bg-success">新</span>
                      <% } %>
                      <%= item.hotValue || '' %>
                    </span>
                  </div>
                <% }); %>
              <% } else { %>
                <div class="list-group-item text-center">
                  <p class="mb-0">暂无热搜数据，请点击"立即爬取"按钮获取最新热搜</p>
                </div>
              <% } %>
            </div>
          </div>
        </div>
        
        <!-- 历史记录卡片 -->
        <div class="card mt-3" id="historyCard" style="display: none;">
          <div class="card-header bg-secondary text-white">
            <h5 class="card-title mb-0">历史热搜数据</h5>
          </div>
          <div class="card-body">
            <div id="historyList" class="mb-3">
              <div class="text-center py-2">
                <div class="spinner-border" role="status">
                  <span class="visually-hidden">Loading...</span>
                </div>
                <p>加载历史数据中...</p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 热搜对比弹窗 -->
    <div class="modal fade" id="compareModal" tabindex="-1" aria-hidden="true">
      <div class="modal-dialog modal-lg">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="compareTitle">热搜对比</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <div class="row">
              <div class="col-md-6">
                <h6 id="compareTimeA" class="text-center mb-3"></h6>
                <div id="compareListA" class="list-group"></div>
              </div>
              <div class="col-md-6">
                <h6 id="compareTimeB" class="text-center mb-3"></h6>
                <div id="compareListB" class="list-group"></div>
              </div>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
          </div>
        </div>
      </div>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', function() {
      // DOM元素
      const hotList = document.getElementById('hotList');
      const updateTime = document.getElementById('updateTime');
      const manualCrawlBtn = document.getElementById('manualCrawl');
      const startScheduleBtn = document.getElementById('startSchedule');
      const stopScheduleBtn = document.getElementById('stopSchedule');
      const cronExpressionInput = document.getElementById('cronExpression');
      const viewHistoryBtn = document.getElementById('viewHistory');
      const historyCard = document.getElementById('historyCard');
      const historyList = document.getElementById('historyList');
      const saveConfigBtn = document.getElementById('saveConfig');
      const saveHistoryDaysInput = document.getElementById('saveHistoryDays');
      const autoStartScheduleInput = document.getElementById('autoStartSchedule');
      
      const compareModal = new bootstrap.Modal(document.getElementById('compareModal'));
      
      // 获取配置信息
      async function loadConfig() {
        try {
          const response = await fetch('/api/config');
          const data = await response.json();
          
          if (data.success) {
            const config = data.config;
            cronExpressionInput.value = config.cronExpression || '*/3 * * * *';
            saveHistoryDaysInput.value = config.saveHistoryDays || 7;
            autoStartScheduleInput.checked = config.autoStartSchedule !== false;
          }
        } catch (error) {
          console.error('获取配置失败:', error);
        }
      }
      
      // 保存配置
      saveConfigBtn.addEventListener('click', async function() {
        try {
          const newConfig = {
            cronExpression: cronExpressionInput.value.trim(),
            saveHistoryDays: parseInt(saveHistoryDaysInput.value) || 7,
            autoStartSchedule: autoStartScheduleInput.checked
          };
          
          const response = await fetch('/api/config', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(newConfig)
          });
          
          const data = await response.json();
          
          if (data.success) {
            alert('配置已保存');
          } else {
            alert('保存配置失败: ' + data.message);
          }
        } catch (error) {
          console.error('保存配置失败:', error);
          alert('保存配置失败，请检查网络连接');
        }
      });
      
      // 加载最新热搜
      async function loadLatestHotSearch() {
        try {
          const response = await fetch('/api/hot');
          const data = await response.json();
          
          if (data.success) {
            renderHotSearchList(data.data);
            updateTime.textContent = new Date().toLocaleString();
          } else {
            hotList.innerHTML = `<div class="list-group-item text-center">
              <p class="mb-0">获取热搜失败: ${data.message}</p>
            </div>`;
          }
        } catch (error) {
          console.error('加载热搜失败:', error);
          hotList.innerHTML = '<div class="list-group-item text-center text-danger">获取热搜数据失败，请检查网络连接</div>';
        }
      }
      
      // 渲染热搜列表
      function renderHotSearchList(data) {
        if (!data || data.length === 0) {
          hotList.innerHTML = '<div class="list-group-item text-center">暂无热搜数据</div>';
          return;
        }
        
        let html = '';
        data.forEach((item, index) => {
          const rank = item.rank || (index + 1);
          const rankClass = rank <= 3 ? `rank-${rank}` : '';
          const hotClass = item.isHot ? 'is-hot' : '';
          const newClass = item.isNew ? 'is-new' : '';
          
          html += `
            <div class="list-group-item d-flex align-items-center hot-item ${hotClass} ${newClass} ${rankClass}">
              <span class="hot-badge">${rank}</span>
              <span class="hot-title">${item.title}</span>
              
              <span class="hot-index">
                ${item.isHot ? '<span class="badge bg-danger">热</span>' : ''}
                ${item.isNew ? '<span class="badge bg-success">新</span>' : ''}
                ${item.hotValue || ''}
              </span>
            </div>
          `;
        });
        
        hotList.innerHTML = html;
      }
      
      // 手动爬取
      manualCrawlBtn.addEventListener('click', async function() {
        manualCrawlBtn.disabled = true;
        manualCrawlBtn.innerHTML = `
          <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
          爬取中...
        `;
        
        try {
          const response = await fetch('/api/crawl', { method: 'POST' });
          const data = await response.json();
          
          if (data.success) {
            renderHotSearchList(data.data);
            updateTime.textContent = data.timestamp || new Date().toLocaleString();
            alert(`成功爬取 ${data.data.length} 条热搜`);
          } else {
            alert(`爬取失败: ${data.message}`);
          }
        } catch (error) {
          console.error('爬取失败:', error);
          alert('爬取失败，请检查网络连接');
        } finally {
          manualCrawlBtn.disabled = false;
          manualCrawlBtn.innerHTML = '立即爬取百度热搜';
        }
      });
      
      // 启动定时任务
      startScheduleBtn.addEventListener('click', async function() {
        const cron = cronExpressionInput.value.trim();
        
        try {
          const response = await fetch('/api/schedule/start', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ cron })
          });
          
          const data = await response.json();
          
          if (data.success && data.started) {
            alert('定时爬取任务已启动');
            startScheduleBtn.disabled = true;
            stopScheduleBtn.disabled = false;
          } else {
            alert(data.message);
          }
        } catch (error) {
          console.error('启动定时任务失败:', error);
          alert('启动定时任务失败，请检查网络连接');
        }
      });
      
      // 停止定时任务
      stopScheduleBtn.addEventListener('click', async function() {
        try {
          const response = await fetch('/api/schedule/stop', { method: 'POST' });
          const data = await response.json();
          
          if (data.success && data.stopped) {
            alert('定时爬取任务已停止');
            startScheduleBtn.disabled = false;
            stopScheduleBtn.disabled = true;
          } else {
            alert(data.message);
          }
        } catch (error) {
          console.error('停止定时任务失败:', error);
          alert('停止定时任务失败，请检查网络连接');
        }
      });
      
      // 加载历史数据
      viewHistoryBtn.addEventListener('click', async function() {
        historyCard.style.display = 'block';
        
        try {
          const response = await fetch('/api/history');
          const data = await response.json();
          
          if (data.success && data.history.length > 0) {
            renderHistoryList(data.history);
          } else {
            historyList.innerHTML = '<div class="alert alert-info">暂无历史数据</div>';
          }
        } catch (error) {
          console.error('获取历史数据失败:', error);
          historyList.innerHTML = '<div class="alert alert-danger">获取历史数据失败，请检查网络连接</div>';
        }
      });
      
      // 渲染历史数据列表
      function renderHistoryList(history) {
        let currentDate = '';
        let html = '';
        
        // 按日期分组
        history.forEach((item, index) => {
          if (item.date !== currentDate) {
            if (currentDate !== '') {
              html += '</div>';
            }
            currentDate = item.date;
            html += `
              <div class="mb-3">
                <h6 class="border-bottom pb-1">${formatDate(item.date)}</h6>
            `;
          }
          
          html += `
            <div class="d-flex justify-content-between align-items-center py-1 px-2 history-item">
              <span>${item.time.replace(/-/g, ':')}</span>
              <button class="btn btn-sm btn-outline-primary view-history" 
                      data-date="${item.date}" 
                      data-time="${item.time}">
                查看
              </button>
            </div>
          `;
        });
        
        if (currentDate !== '') {
          html += '</div>';
        }
        
        historyList.innerHTML = html;
        
        // 绑定查看历史数据事件
        document.querySelectorAll('.view-history').forEach(btn => {
          btn.addEventListener('click', async function() {
            const date = this.getAttribute('data-date');
            const time = this.getAttribute('data-time');
            
            try {
              const response = await fetch(`/api/history/${date}/${time}`);
              const data = await response.json();
              
              if (data.success) {
                // 显示与当前热搜的对比
                showCompareModal(data.data, date, time);
              } else {
                alert(`获取历史数据失败: ${data.message}`);
              }
            } catch (error) {
              console.error('获取历史数据失败:', error);
              alert('获取历史数据失败，请检查网络连接');
            }
          });
        });
      }
      
      // 显示对比弹窗
      async function showCompareModal(historyData, date, time) {
        // 获取当前热搜数据
        const currentResponse = await fetch('/api/hot');
        const currentData = await currentResponse.json();
        
        if (!currentData.success) {
          alert('获取当前热搜数据失败');
          return;
        }
        
        // 设置标题
        document.getElementById('compareTimeA').textContent = `${formatDate(date)} ${time.replace(/-/g, ':')}`;
        document.getElementById('compareTimeB').textContent = '当前热搜';
        
        // 渲染历史热搜
        let htmlA = '';
        historyData.forEach((item, index) => {
          htmlA += `
            <div class="list-group-item">
              <span class="badge bg-secondary">${item.rank || (index + 1)}</span>
              ${item.title}
            </div>
          `;
        });
        document.getElementById('compareListA').innerHTML = htmlA;
        
        // 渲染当前热搜
        let htmlB = '';
        currentData.data.forEach((item, index) => {
          htmlB += `
            <div class="list-group-item">
              <span class="badge bg-secondary">${item.rank || (index + 1)}</span>
              ${item.title}
            </div>
          `;
        });
        document.getElementById('compareListB').innerHTML = htmlB;
        
        // 显示弹窗
        compareModal.show();
      }
      
      // 格式化日期
      function formatDate(dateStr) {
        const date = new Date(dateStr);
        return date.toLocaleDateString('zh-CN', { 
          year: 'numeric', 
          month: 'long', 
          day: 'numeric', 
          weekday: 'long' 
        });
      }
      
      // 初始加载
      loadConfig();
    });
  </script>
  
  <footer class="footer">
    <div class="container">
      <p>© 2023 百度热搜爬虫 - 基于Node.js和Puppeteer构建</p>
      <p>
        <small>一个轻量级的热搜监控工具，定时抓取并保存百度热搜榜数据</small>
      </p>
    </div>
  </footer>
</body>
</html> 